/*
 * XXX
 */

package edu.uhcl.csci4838.group3.view;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.SimpleCursorTreeAdapter;
import android.widget.Toast;
import edu.uhcl.csci4838.group3.R;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper.CursorCourse;
import edu.uhcl.csci4838.group3.database.BackpackEduDatabaseHelper.CursorSemester;
import edu.uhcl.csci4838.group3.database.info.Course;
import edu.uhcl.csci4838.group3.database.info.Semester;
import edu.uhcl.csci4838.group3.view.help.HelpActivity;

/**
 * XXX
 * 
 * @author Chris Waguespack
 */
public class CourseListActivity extends ExpandableListActivity {
	
	/**
	 * XXX
	 * 
	 * @author Chris Waguespack
	 */
	private static class CoursesCursorTreeAdapter extends
			SimpleCursorTreeAdapter {
		/**
		 * XXX
		 * 
		 * @param context
		 *            XXX
		 * @param cursor
		 *            XXX
		 * @param collapsedGroupLayout
		 *            XXX
		 * @param expandedGroupLayout
		 *            XXX
		 * @param groupFrom
		 *            XXX
		 * @param groupTo
		 *            XXX
		 * @param childLayout
		 *            XXX
		 * @param lastChildLayout
		 *            XXX
		 * @param childFrom
		 *            XXX
		 * @param childTo
		 *            XXX
		 */
		public CoursesCursorTreeAdapter(final Context context,
				final Cursor cursor,
				final int collapsedGroupLayout,
				final int expandedGroupLayout,
				final String[] groupFrom,
				final int[] groupTo,
				final int childLayout,
				final int lastChildLayout,
				final String[] childFrom,
				final int[] childTo) {
			super(context,
					cursor,
					collapsedGroupLayout,
					expandedGroupLayout,
					groupFrom,
					groupTo,
					childLayout,
					lastChildLayout,
					childFrom,
					childTo);
		}
		
		/**
		 * XXX
		 * 
		 * @param context
		 *            XXX
		 * @param cursor
		 *            XXX
		 * @param collapsedGroupLayout
		 *            XXX
		 * @param expandedGroupLayout
		 *            XXX
		 * @param groupFrom
		 *            XXX
		 * @param groupTo
		 *            XXX
		 * @param childLayout
		 *            XXX
		 * @param childFrom
		 *            XXX
		 * @param childTo
		 *            XXX
		 */
		public CoursesCursorTreeAdapter(final Context context,
				final Cursor cursor,
				final int collapsedGroupLayout,
				final int expandedGroupLayout,
				final String[] groupFrom,
				final int[] groupTo,
				final int childLayout,
				final String[] childFrom,
				final int[] childTo) {
			super(context,
					cursor,
					collapsedGroupLayout,
					expandedGroupLayout,
					groupFrom,
					groupTo,
					childLayout,
					childFrom,
					childTo);
		}
		
		/**
		 * XXX
		 * 
		 * @param context
		 *            XXX
		 * @param cursor
		 *            XXX
		 * @param groupLayout
		 *            XXX
		 * @param groupFrom
		 *            XXX
		 * @param groupTo
		 *            XXX
		 * @param childLayout
		 *            XXX
		 * @param childFrom
		 *            XXX
		 * @param childTo
		 *            XXX
		 */
		public CoursesCursorTreeAdapter(final Context context,
				final Cursor cursor,
				final int groupLayout,
				final String[] groupFrom,
				final int[] groupTo,
				final int childLayout,
				final String[] childFrom,
				final int[] childTo) {
			super(context,
					cursor,
					groupLayout,
					groupFrom,
					groupTo,
					childLayout,
					childFrom,
					childTo);
		}
		
		/**
		 * XXX
		 * 
		 * @param groupCursor
		 *            XXX
		 * @return XXX
		 */
		/* 
		 * (non-Javadoc)
		 * 
		 * @see android.widget.CursorTreeAdapter#getChildrenCursor(android.database.Cursor)
		 */
		@SuppressWarnings("synthetic-access")
		@Override
		protected Cursor getChildrenCursor(final Cursor groupCursor) {
			if (!(groupCursor instanceof CursorSemester)) {
				Log.e("BackpackEDU",
						"Group cursor is not a semester cursor.");
				throw new ClassCastException("Group cursor is not a semester cursor.");
			}
			
			final ContentValues criteria = new ContentValues();
			criteria.put(Course.SEMESTER_ID,
					Long.valueOf(((CursorSemester) groupCursor).getColId()));
			return CourseListActivity.dbHelper.getCourse(criteria,
					new String[] { Course.NAME },
					true);
		}
	}
	
	/**
	 * The database helper object.
	 */
	private static BackpackEduDatabaseHelper dbHelper;
	
	/**
	 * The adapter used to bind data to this list.
	 */
	private CoursesCursorTreeAdapter adapter;
	
	/**
	 * A list of the opened group positions;
	 */
	private ArrayList<Integer> openedGroups;
	
	/**
	 * XXX
	 * 
	 * @param parent
	 *            XXX
	 * @param v
	 *            XXX
	 * @param groupPosition
	 *            XXX
	 * @param childPosition
	 *            XXX
	 * @param id
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.ExpandableListActivity#onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long)
	 */
	@Override
	public boolean onChildClick(final ExpandableListView parent,
			final View v,
			final int groupPosition,
			final int childPosition,
			final long id) {
		this.adapter.getCursor()
				.moveToPosition(groupPosition);
		
		// Get the course cursor
		final CursorCourse courseCursor = (CursorCourse) this.adapter.getChildrenCursor(this.adapter.getCursor());
		courseCursor.moveToPosition(childPosition);
		
		// Start course activity
		final Intent intent = new Intent(this.getApplicationContext(),
				CourseActivity.class);
		intent.putExtra(getString(R.string.intent_extra_courseId),
				courseCursor.getColId());
		courseCursor.close();
		this.startActivity(intent);
		return true;
	}
	
	/**
	 * XXX
	 * 
	 * @param item
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onContextItemSelected(final MenuItem item) {
		
		// Get information about the selected item
		final ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo();
		final int type = ExpandableListView.getPackedPositionType(info.packedPosition);
		final int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
		final int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
		
		// Set up the semester cursor information
		final CursorSemester semesterCursor = (CursorSemester) this.adapter.getCursor();
		semesterCursor.moveToPosition(groupPos);
		
		// Trigger the right action
		switch (type) {
			case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
				// Trigger the right semester action
				switch (item.getItemId()) {
					case R.id.menu_item_view_semester:
						this.startActivity(new Intent(this.getApplicationContext(),
								SemesterActivity.class).putExtra(getString(R.string.intent_extra_semesterId),
								semesterCursor.getColId()));
						return true;
					case R.id.menu_item_edit_semester:
						this.startActivity(new Intent(this.getApplicationContext(),
								EditSemesterActivity.class).putExtra(getString(R.string.intent_extra_semesterId),
								semesterCursor.getColId()));
						return true;
					case R.id.menu_item_rename_semester:
						this.showRenameSemesterDialog(semesterCursor.getColId(),
								semesterCursor.getColName());
						return true;
					case R.id.menu_item_delete_semester:
						this.showDeleteSemesterDialog(semesterCursor.getColId(),
								semesterCursor.getColName());
						return true;
					default:
						return super.onContextItemSelected(item);
				}
			case ExpandableListView.PACKED_POSITION_TYPE_CHILD:
				// Set up the course cursor information
				final CursorCourse courseCursor = (CursorCourse) this.adapter.getChildrenCursor(semesterCursor);
				courseCursor.moveToPosition(childPos);
				
				// Trigger the right course option
				switch (item.getItemId()) {
					case R.id.menu_item_view_course:
						this.startActivity(new Intent(this.getApplicationContext(),
								CourseActivity.class).putExtra(getString(R.string.intent_extra_courseId),
								courseCursor.getColId()));
						courseCursor.close();
						return true;
					case R.id.menu_item_edit_course:
						this.startActivity(new Intent(this.getApplicationContext(),
								EditCourseInfoActivity.class).putExtra(getString(R.string.intent_extra_courseId),
								courseCursor.getColId()));
						courseCursor.close();
						return true;
					case R.id.menu_item_rename_course:
						this.showRenameCourseDialog(courseCursor.getColId(),
								courseCursor.getColName());
						courseCursor.close();
						return true;
					case R.id.menu_item_delete_course:
						this.showDeleteCourseDialog(courseCursor.getColId(),
								courseCursor.getColName());
						courseCursor.close();
						return true;
					default:
						courseCursor.close();
						return super.onContextItemSelected(item);
				}
			default: // ExpandableListView.PACKED_POSITION_TYPE_NULL
				Log.wtf("BackpackEDU",
						"Packed position is null.");
				return super.onContextItemSelected(item);
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param menu
	 *            XXX
	 * @param v
	 *            XXX
	 * @param menuInfo
	 *            XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
	 */
	@Override
	public void onCreateContextMenu(final ContextMenu menu,
			final View v,
			final ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu,
				v,
				menuInfo);
		// Get information about the selected item
		final ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
		final int type = ExpandableListView.getPackedPositionType(info.packedPosition);
		final int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
		final int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
		
		// Get ready to show the context menu
		final MenuInflater inflater = this.getMenuInflater();
		final CursorSemester semesterCursor = (CursorSemester) this.adapter.getCursor();
		semesterCursor.moveToPosition(groupPos);
		switch (type) {
			case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
				// Show the semester context menu
				menu.setHeaderTitle(semesterCursor.getColName());
				inflater.inflate(R.menu.context_courselist_semester,
						menu);
				break;
			case ExpandableListView.PACKED_POSITION_TYPE_CHILD:
				// Show the course context menu
				final CursorCourse courseCursor = (CursorCourse) this.adapter.getChildrenCursor(semesterCursor);
				courseCursor.moveToPosition(childPos);
				menu.setHeaderTitle(courseCursor.getColName());
				courseCursor.close();
				inflater.inflate(R.menu.context_courselist_course,
						menu);
				break;
			default: // ExpandableListView.PACKED_POSITION_TYPE_NULL
				Log.wtf("BackpackEDU",
						"Packed position is null.");
				break;
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param menu
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(final Menu menu) {
		this.getMenuInflater()
				.inflate(R.menu.options_courselist,
						menu);
		return true;
	}
	
	/**
	 * XXX
	 * 
	 * @param groupPosition
	 *            XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.ExpandableListActivity#onGroupCollapse(int)
	 */
	@Override
	public void onGroupCollapse(final int groupPosition) {
		if (!this.openedGroups.remove(Integer.valueOf(groupPosition))) {
			Log.e("BackpackEDU",
					"Could not remove group position from opened group list.");
		}
		super.onGroupCollapse(groupPosition);
	}
	
	/**
	 * XXX
	 * 
	 * @param groupPosition
	 *            XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.ExpandableListActivity#onGroupExpand(int)
	 */
	@Override
	public void onGroupExpand(final int groupPosition) {
		this.openedGroups.add(Integer.valueOf(groupPosition));
		super.onGroupExpand(groupPosition);
	}
	
	/**
	 * XXX
	 * 
	 * @param item
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		switch (item.getItemId()) {
			case R.id.menu_item_add_semester:
				this.startActivity(new Intent(this.getApplicationContext(),
						EditSemesterActivity.class));
				return true;
			case R.id.menu_item_add_course:
				this.startActivity(new Intent(this.getApplicationContext(),
						EditCourseInfoActivity.class));
				return true;
			case R.id.menu_item_view_faculty_list:
				this.startActivity(new Intent(this.getApplicationContext(),
						FacultyListActivity.class));
				return true;
			case R.id.menu_item_settings:
				 this.startActivity(new Intent(this.getApplicationContext(),
						 SettingsActivity.class));
				return true;
			case R.id.menu_item_about:
				 this.startActivity(new Intent(getApplicationContext(),
						 AboutActivity.class));
				return true;
			case R.id.menu_item_help:
				this.startActivity(new Intent(getApplicationContext(),
						HelpActivity.class));
				return true;
			default:
				Log.wtf("BackpackEDU",
						"Undefined options menu item.");
				return super.onOptionsItemSelected(item);
		}
	}
	
	/**
	 * XXX
	 * 
	 * @param menu
	 *            XXX
	 * @return XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onPrepareOptionsMenu(final Menu menu) {
		final MenuItem item = menu.findItem(R.id.menu_item_add_course);
		if (item != null) {
			// Don't show 'Add course' if there are no semesters
			if (this.adapter.getCursor()
					.getCount() == 0) {
				item.setEnabled(false);
			} else {
				item.setEnabled(true);
			}
		}
		
		return super.onPrepareOptionsMenu(menu);
	}
	
	/**
	 * XXX
	 * 
	 * @param savedInstanceState
	 *            XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		this.setContentView(R.layout.activity_course_list);
		
		// Start the database helper
		CourseListActivity.dbHelper = new BackpackEduDatabaseHelper(this);
		
		// Fill the data
		final CursorSemester semesterCursor = CourseListActivity.dbHelper.getSemester(null,
				new String[] { Semester.CREATION_DATE },
				false);
		this.startManagingCursor(semesterCursor);
		
		// Set up the adapter
		this.adapter = new CoursesCursorTreeAdapter(this,
				semesterCursor,
				R.layout.category,
				new String[] { Semester.NAME },
				new int[] { R.id.tv_category },
				R.layout.item,
				new String[] { Course.NAME },
				new int[] { R.id.tv_item });
		this.setListAdapter(this.adapter);
		
		// Expand the groups
		this.openedGroups = new ArrayList<Integer>();
		if (this.adapter.getGroupCount() > 0) {
			this.getExpandableListView()
					.expandGroup(0);
		}
		
		// Let this view have a context menu
		this.registerForContextMenu(this.getExpandableListView());
	}
	
	/**
	 * XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onDestroy()
	 */
	@Override
	protected void onDestroy() {
		CourseListActivity.dbHelper.close();
		super.onDestroy();
	}
	
	/**
	 * XXX
	 */
	/* 
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onRestart()
	 */
	@Override
	@SuppressWarnings("unchecked")
	protected void onRestart() {
		// Requery the semester cursor
		// TODO [Chris W] Do I actually need this?
		this.adapter.notifyDataSetChanged();
		
		// Reopen all the groups that were open
		// TODO test this after deleting a semester
		final Object clone = this.openedGroups.clone();
		if (!(clone instanceof ArrayList<?>)) {
			Log.e("BackpackEDU",
					"Cloned list is not an array list.");
			throw new ClassCastException("Cloned list is not an array list.");
		}
		
		final ArrayList<Integer> opened = (ArrayList<Integer>) clone;
		for (final Integer groupPos : opened) {
			this.getExpandableListView()
					.expandGroup(groupPos.intValue());
		}
		
		super.onRestart();
	}
	
	/**
	 * XXX
	 * 
	 * @param courseId
	 *            XXX
	 * @param courseName
	 *            XXX
	 */
	private void showDeleteCourseDialog(final long courseId,
			final String courseName) {
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.menu_title_delete_course)
				.setMessage("Are you sure you want to delete the course \""
						+ courseName
						+ "\" and all of its associated tasks?")
				.setPositiveButton("Delete",
						new DialogInterface.OnClickListener() {
							
							@SuppressWarnings("synthetic-access")
							@Override
							public void onClick(final DialogInterface dialog,
									final int which) {
								CourseListActivity.dbHelper.deleteCourse(courseId);
								CourseListActivity.this.adapter.notifyDataSetChanged();
								
							}
						})
				.setNegativeButton(android.R.string.cancel,
						new CancelListener());
		final AlertDialog alert = builder.create();
		alert.show();
	}
	
	/**
	 * XXX
	 * 
	 * @param semesterId
	 *            XXX
	 * @param semesterName
	 *            XXX
	 */
	private void showDeleteSemesterDialog(final long semesterId,
			final String semesterName) {
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.menu_title_delete_semester)
				.setMessage("Are you sure you want to delete the semester \""
						+ semesterName
						+ "\" and all of its associated classes?")
				.setPositiveButton("Delete",
						new DialogInterface.OnClickListener() {
							
							@SuppressWarnings("synthetic-access")
							@Override
							public void onClick(final DialogInterface dialog,
									final int which) {
								CourseListActivity.dbHelper.deleteSemester(semesterId);
								CourseListActivity.this.adapter.getCursor()
										.requery();
							}
						})
				.setNegativeButton(android.R.string.cancel,
						new CancelListener());
		final AlertDialog alert = builder.create();
		alert.show();
	}
	
	/**
	 * XXX
	 * 
	 * @param courseId
	 *            XXX
	 * @param courseName
	 *            XXX
	 */
	private void showRenameCourseDialog(final long courseId,
			final String courseName) {
		final LayoutInflater inflater = this.getLayoutInflater();
		final View layout = inflater.inflate(R.layout.dialog_rename_course,
				(ViewGroup) this.findViewById(R.id.dialog_rename_course));
		final EditText editText = (EditText) layout.findViewById(R.id.edit_course);
		editText.setText(courseName);
		editText.selectAll();
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setView(layout)
				.setTitle(R.string.menu_title_rename_course)
				.setPositiveButton("Rename",
						new DialogInterface.OnClickListener() {
							
							@SuppressWarnings("synthetic-access")
							@Override
							public void onClick(final DialogInterface dialog,
									final int which) {
								final String newCourse = editText.getText()
										.toString()
										.trim();
								final ContentValues criteria = new ContentValues();
								criteria.put(Course.NAME,
										newCourse);
								final boolean editOk = CourseListActivity.dbHelper.editCourse(courseId,
										criteria);
								if (editOk) {
									CourseListActivity.this.adapter.notifyDataSetChanged();
								} else {
									Toast.makeText(CourseListActivity.this,
											"Course \""
													+ newCourse
													+ "\" already exists!",
											Toast.LENGTH_LONG)
											.show();
								}
								
							}
						})
				.setNegativeButton(android.R.string.cancel,
						new CancelListener());
		final AlertDialog alert = builder.create();
		alert.show();
	}
	
	/**
	 * XXX
	 * 
	 * @param semesterId
	 *            XXX
	 * @param semesterName
	 *            XXX
	 */
	private void showRenameSemesterDialog(final long semesterId,
			final String semesterName) {
		final LayoutInflater inflater = this.getLayoutInflater();
		final View layout = inflater.inflate(R.layout.dialog_rename_semester,
				(ViewGroup) this.findViewById(R.id.dialog_rename_semester));
		final EditText editText = (EditText) layout.findViewById(R.id.edit_semester);
		editText.setText(semesterName);
		editText.selectAll();
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setView(layout)
				.setTitle(R.string.menu_title_rename_semester)
				.setPositiveButton("Rename",
						new DialogInterface.OnClickListener() {
							
							@SuppressWarnings("synthetic-access")
							@Override
							public void onClick(final DialogInterface dialog,
									final int which) {
								final String newSemester = editText.getText()
										.toString()
										.trim();
								final ContentValues criteria = new ContentValues();
								criteria.put(Semester.NAME,
										newSemester);
								final boolean editOk = CourseListActivity.dbHelper.editSemester(semesterId,
										criteria);
								if (editOk) {
									CourseListActivity.this.adapter.getCursor()
											.requery();
								} else {
									Toast.makeText(CourseListActivity.this,
											"Semester \""
													+ newSemester
													+ "\" already exists!",
											Toast.LENGTH_LONG)
											.show();
								}
								
							}
						})
				.setNegativeButton(android.R.string.cancel,
						new CancelListener());
		final AlertDialog alert = builder.create();
		alert.show();
	}
}
